#include "metanet_imp.h"

#include <stdio.h>
#include <signal.h>
#include <stddef.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

#include <unistd.h>
#include <pthread.h>

#include "metanet_malloc.h"
#include "metanet_daemon.h"
#include "metanet_handle.h"
#include "metanet_mq.h"
#include "metanet_module.h"
#include "metanet_server.h"
#include "metanet.h"


struct worker_param {
    int id;
    int weight;
};

static int SIG = 0;

static void
handle_hup(int signal) {
    if (signal == SIGHUP) {
        SIG = 1;
    }
}

static void
create_pthread(pthread_t *thread, void *(*start_routine)(void*), void *arg) {
    if (pthread_create(thread, NULL, start_routine, arg)) {
        fprintf(stderr, "Create thread failed");
        exit(1);
    }
}

// static uint64_t
// gettime() {
//     uint64_t t;
//     struct timespec ts;
//     clock_gettime(CLOCK_MONOTONIC, &ts);
//     t = (uint64_t)ts.tv_sec * 1000;
//     t += ts.tv_nsec / 1000000;
//     return t;
// }

static void *
thread_worker(void *p) {
    struct worker_param *wp = (struct worker_param*)p;
    // int id = wp->id;
    int weight = wp->weight;
    struct metanet_message_queue *mq = NULL;
    struct metanet_context *ctx = NULL;
    char *msg = "hello world!";
    size_t sz = strlen(msg);

    char *test_msg = "test msg!";
    size_t test_msg_sz = strlen(test_msg);
    int i = 0;
    while (1) {
        mq = metanet_context_message_dispatch(mq, weight); //dispatch
        usleep(100);
        //todo test
        if (i < 100) {
            ++i;
            uint32_t handle = metanet_handle_findname("logger");
            ctx = metanet_handle_grab(handle);
            char *send_msg = metanet_malloc(sz + 1);
            strcpy(send_msg, msg);
            metanet_context_send(ctx, send_msg, sz, handle, PTYPE_TAG_ALLOCSESSION, 0);

            uint32_t test_handle = metanet_handle_findname("test");
            struct metanet_context *test_ctx = metanet_handle_grab(test_handle);
            send_msg = metanet_malloc(test_msg_sz + 1);
            strcpy(send_msg, test_msg);
            metanet_send(test_ctx, test_handle, handle, PTYPE_TAG_ALLOCSESSION | PTYPE_TEST, 0, send_msg, sz);
        } else {
            if (mq == NULL) {
                break;
            }
        }
    }

    return NULL; //
}

static void
start(int thread) {
    pthread_t pid[thread];
    int i;
    static int weight[] = {0,};
    struct worker_param wp[thread];
    for (i = 0; i < thread; ++i) {
        wp[i].id = i;
        if (i < sizeof(weight)/sizeof(weight[0])) {
            wp[i].weight = weight[i];
        } else {
            wp[i].weight = 0;
        }
        create_pthread(&pid[i], thread_worker, &wp[i]);
    }

    for (i = 0; i < thread; ++i) {
        pthread_join(pid[i], NULL);
    }
}

// static void
// bootstrap(struct metanet_context *logger, const char *cmdline) {
//     size_t sz = strlen(cmdline);
//     char name[sz+1];
//     char args[sz+1];
//     sscanf(cmdline, "%s %s", name,args);
//     struct metanet_context *ctx = metanet_context_new(name, args);
//     if (ctx == NULL) {
//         metanet_error(ctx, "Bootstrap error : %s\n", cmdline);
//         metanet_context_message_dispatchall(logger);
//         exit(1);
//     }
// }

void
metanet_start(struct metanet_config *config) {
    struct sigaction sa;
    sa.sa_handler = &handle_hup;
    sa.sa_flags = SA_RESTART;
    sigfillset(&sa.sa_mask);
    sigaction(SIGHUP, &sa, NULL);

    // if (config->daemon) {
    //     if (daemon_init(config->daemon)) {
    //         exit(1);
    //     }
    // }

    metanet_mq_init();
    metanet_handle_init(config->harbor);
    metanet_module_init("./service-lib/?.so");

    struct metanet_context *ctx = metanet_context_new(config->logservice, config->logger);
    if (ctx == NULL) {
        fprintf(stderr, "Cant't launch %s service\n", config->logservice);
    }
    metanet_handle_namehandle(metanet_context_handle(ctx), "logger");

    //
    ctx = metanet_context_new("test", "");
    if (ctx == NULL) {
        fprintf(stderr, "Cant't launch %s services\n", "test");
        abort();
    }
    metanet_handle_namehandle(metanet_context_handle(ctx), "test");


    // bootstrap(ctx, config->bootstrap);

    start(config->thread);

    // if (config->daemon) {
    //     daemon_exit(config->daemon);
    // }
    // metanet_handle_exit();
    // metanet_mq_exit();
}